#include "BulletSystem.h"
#include "MathUtiles.h"

#include "BulletComponent.h"
#include "PhysicComponents.h"
#include "GraphicComponents.h"
#include "ParticleComponent.h"
#include "PositionComponent.h"

#include "RenderSystem.h"
#include "PhysicSystem.h"

#include "GameState.h"
#include <cmath>

BulletSystem::BulletSystem()
{

}
void BulletSystem::update(float dt)
{
	for(std::set<int>::iterator itr = mpt_entitiesID.begin(); itr != mpt_entitiesID.end();)
	{
		if(entityManager->hasEntity((*itr)))
		{
			BulletComponentPtr bullet = entityManager->getEntity(*itr)->getAs<BulletComponent>();
			bullet->timeElapsed += dt;

			if(bullet->type == BulletComponent::NORMAL)
			{
				DynamicComponentPtr bulletPhys = entityManager->getEntity(*itr)->getAs<DynamicComponent>();

				bullet->direction.y = bullet->trajectoire->getPath(bullet->timeElapsed);
				if(bullet->direction.y > 1)
					bullet->direction.y = 1;
				else if(bullet->direction.y < -1)
					bullet->direction.y = -1;
				bullet->direction.x = sin(acos(bullet->direction.y));

				bullet->direction = normalize(bullet->direction);

				// VERIFIER LA DISTANCE AU TIREUR
				if(bulletPhys->collide && bullet->IDlauncher != bulletPhys->collideWith && mpt_entitiesID.find(bullet->IDlauncher)==mpt_entitiesID.end())
				{
					if(bulletPhys->normalCollision.x != 0)
					{
						bullet->horizontalOrientation *= -1;
						ModelGraphicComponentPtr graph = entityManager->getEntity(*itr)->getAs<ModelGraphicComponent>();
						if(bullet->horizontalOrientation == 1)
							graph->model.flipX(false);
						else
							graph->model.flipX(true);
					}
					if(bulletPhys->normalCollision.y != 0)
						bullet->verticalOrientation *= -1;
					
					bullet->rebounds--;
					if(bullet->rebounds < 0)
					{
						int random = std::rand()%3 + 2;
						PositionComponentPtr positionBullet = entityManager->getEntity(*itr)->getAs<PositionComponent>();
						GameState* state = static_cast<GameState*>(mpt_parent);
						//CREER UN ENSEMBLE DE PARTICULES AU CRASH (A DONNER AU PARTICULE SYSTEM)
						for(int i = 0; i<random; i++)
						{
							GraphicComponentPtr graph(new GraphicComponent);
							JumpingComponentPtr phys(new JumpingComponent);
							ParticleComponentPtr particle(new ParticleComponent);
							PositionComponentPtr position(new PositionComponent);

							sf::RectangleShape* rect = new sf::RectangleShape(sf::Vector2f(5,5));
							rect->setFillColor(sf::Color(20,200,40));
								
							graph->m_sprite = rect;
							graph->m_transform.setOrigin(3,3);

							position->m_position = positionBullet->m_position;
							position->m_center = graph->m_transform.getOrigin();

							phys->jumpSpeed = 400.0f;
							phys->jumpLength = 1.5;
							phys->jumpState = getFloatRandom(-0.5f,0.2f);
							phys->speed = 50;
							phys->sizeBox = sf::Vector2f(3.0f,3.0f);

							particle->direction = bulletPhys->normalCollision;
							particle->physic = true;
							particle->time = 0.5f;

							BPL::EntityPtr e(new BPL::Entity(entityManager->getNextAvailableID()));
							entityManager->registerDynamicEntity(e, position->m_position,0);
							
							entityManager->addComponent<GraphicComponent>((BPL::EntityId)e->getID(), graph);
							entityManager->addComponent<PhysicComponent>((BPL::EntityId)e->getID(), phys);
							entityManager->addComponent<PositionComponent>((BPL::EntityId)e->getID(), position);
							entityManager->addComponent<ParticleComponent>((BPL::EntityId)e->getID(), particle);

							state->mpt_renderSystem->addEntity(e->getID());
							state->mpt_physicSystem->addEntity(e->getID());
							state->mpt_particuleSystem->addEntity(e->getID());
						}
						
						
					}
				}
				
				bullet->direction.x *= bullet->horizontalOrientation;
				bullet->direction.y *= bullet->verticalOrientation;
				bulletPhys->moveDirection = bulletPhys->speed * bullet->direction;
				itr++;
			}
			else
			{
				JumpingComponentPtr bulletPhys = entityManager->getEntity(*itr)->getAs<JumpingComponent>();
				
				bulletPhys->jumpState += bulletPhys->jumpLength*dt;
				if(bulletPhys->jumpState>1)
					bulletPhys->jumpState = 1;

				if(bulletPhys->collide && mpt_entitiesID.find(bullet->IDlauncher)==mpt_entitiesID.end())
				{
					if(bulletPhys->normalCollision.x != 0 && bulletPhys->normalCollision.y == 0)
						bullet->horizontalOrientation *= -1;
					if(bulletPhys->normalCollision.y != 0)
					{
						if(bulletPhys->normalCollision.y < 0) 
						{
							bulletPhys->jumpState = -bulletPhys->jumpState/2;

							if(bulletPhys->jumpState > -0.25)
							{
								bullet->stop = true;
							}
						}
					}
					//CREER UN ENSEMBLE DE PARTICULES AU CRASH (A DONNER AU PARTICULE SYSTEM)
				}
				
				if(!bullet->stop)
				{
					bullet->direction.x = bulletPhys->speed * bullet->horizontalOrientation;
					bullet->direction.y = bulletPhys->jumpSpeed*bulletPhys->jumpState;
					bulletPhys->moveDirection = bullet->direction;
				}

				if(bullet->timeElapsed > bullet->timeBeforeDeath)
				{
					int random = getIntRandom(3,5);
					PositionComponentPtr positionBullet = entityManager->getEntity(*itr)->getAs<PositionComponent>();
					GameState* state = static_cast<GameState*>(mpt_parent);
					//CREER UN ENSEMBLE DE PARTICULES AU CRASH (A DONNER AU PARTICULE SYSTEM)
					for(int i = 0; i<random; i++)
					{
						GraphicComponentPtr graph(new GraphicComponent);
						JumpingComponentPtr phys(new JumpingComponent);
						ParticleComponentPtr particle(new ParticleComponent);
						PositionComponentPtr position(new PositionComponent);

						sf::RectangleShape* rect = new sf::RectangleShape(sf::Vector2f(7,7));
						rect->setFillColor(sf::Color(200,20,40));
							
						graph->m_sprite = rect;
						graph->m_transform.setOrigin(4,4);

						position->m_position = positionBullet->m_position;
						position->m_center = graph->m_transform.getOrigin();

						phys->jumpSpeed = 500.0f;
						phys->jumpLength = 3.0;
						phys->jumpState = getFloatRandom(-1.0f, -0.3f);
						phys->speed = 50;
						phys->sizeBox = sf::Vector2f(7.0f,7.0f);

						particle->direction = normalize(sf::Vector2f(getFloatRandom(-1.0f, 1.0f), getFloatRandom(-1.0f, 0.0f)));

						particle->physic = true;
						particle->time = 0.5f;

						BPL::EntityPtr e(new BPL::Entity(entityManager->getNextAvailableID()));
						entityManager->registerDynamicEntity(e, position->m_position,0);
						
						entityManager->addComponent<GraphicComponent>((BPL::EntityId)e->getID(), graph);
						entityManager->addComponent<PhysicComponent>((BPL::EntityId)e->getID(), phys);
						entityManager->addComponent<PositionComponent>((BPL::EntityId)e->getID(), position);
						entityManager->addComponent<ParticleComponent>((BPL::EntityId)e->getID(), particle);

						state->mpt_renderSystem->addEntity(e->getID());
						state->mpt_physicSystem->addEntity(e->getID());
						state->mpt_particuleSystem->addEntity(e->getID());
					}
				}

				itr++;
			}
		}
		else
		{
#ifdef DEFINE_MODE
			std::string str = "BUG BULLET : ";
			str += boost::lexical_cast<std::string>(*itr);
			BPL::Logger::log(str.c_str());
#endif
			itr = mpt_entitiesID.erase(itr);
		}
	}
}
